#include <map>
#include <list>
#include <iostream>

using namespace std;

struct RegisterBase;
struct EventBase;
bool isReg = true;
list<RegisterBase*> registerList;
map<size_t, map<size_t, list<EventBase*>>> eventMap;

struct RegisterBase
{
	size_t _type = 0;
	size_t _step = 0;

	virtual void exec() = 0;
};


template <typename RegTy>
struct Register : public RegisterBase
{
	Register(size_t type, size_t step)
	{
		_type = type;
		_step = step;
	}

	void exec() override
	{
		eventMap[_type][_step].push_back(new RegTy);
	}
};

enum EventType
{
	EventType_Init,
	EventType_Online,
	EventType_Offline,
};

struct EventBase
{
	string name;

	virtual void exec() = 0;
};

template <typename EvtTy, EventType EvtTyEm, size_t step = 0>
struct Event : public EventBase
{
	Event()
	{
		if (isReg)
			registerList.push_back(new Register<EvtTy>(EvtTyEm, step));
	}

};

struct EventInit1 : public Event<EventInit1, EventType_Init>
{
	EventInit1()
	{
		name = "EventInit1";
	}

	void exec() override
	{
		cout << "EventInit1" << endl;
	}
} regEventInit1;

struct EventInit2 : public Event<EventInit2, EventType_Init>
{
	EventInit2()
	{
		name = "EventInit2";
	}

	void exec() override
	{
		cout << "EventInit2" << endl;
	}
} regEventInit2;

struct EventInit2_1 : public Event<EventInit2_1, EventType_Init, 1>
{
	EventInit2_1()
	{
		name = "EventInit2_1";
	}

	void exec() override
	{
		cout << "EventInit2_1" << endl;
	}
} regEventInit2_1;




void doEvent(EventType EvtTy)
{
	
}



int main()
{
	isReg = false;
	cout << registerList.size() << endl;
	for (auto pReg : registerList)
	{
		pReg->exec();
		delete pReg;
	}
	registerList.clear();

	bool fstEvt = true;
	for (auto& evt : eventMap)
	{
		if (fstEvt) fstEvt = false;
		else cout << ",";
		
		cout << "[" << evt.first << "]={";
		bool fstStep = true;
		for (auto& step : evt.second)
		{
			if (fstStep) fstStep = false;
			else cout << ",";

			cout << "[" << step.first << "]={";
			bool fstEnt = true;
			for (auto pEnt : step.second)
			{
				if (fstEnt) fstEnt = false;
				else cout << ",";

				cout << pEnt->name;
			}
			cout << "}";
		}

		cout << "}";
	}

	return 0;
}